#include "FFVidClip.h"

#include "util/tc_singleton.h"
#include "servant/RemoteLogger.h"

#include <fstream>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <vector>
#include <string>
#include <cstring>
#include <cstdlib>

extern "C" {
    #include "libavutil/avutil.h"
    #include "libavcodec/avcodec.h"
    #include "libavformat/avformat.h"
    #include "libavutil/imgutils.h"
    #include "libswscale/swscale.h"
    #include "libswresample/swresample.h"
    #include "libavfilter/avfilter.h"
    #include "libavdevice/avdevice.h"
}

#define FLOG_INFO(name) FDLOG(name) << "[info]" << FILE_FUNC_LINE << "|"
#define FLOG_WARN(name) FDLOG(name) << "[warn]" << FILE_FUNC_LINE << "|"
#define FLOG_ERROR(name) FDLOG(name) << "[error]" << FILE_FUNC_LINE << "|"
#define FLOG_FATAL(name) FDLOG(name) << "[fatal]" << FILE_FUNC_LINE << "|"

class FFLogic : public taf::TC_Singleton<FFLogic>
{
public:

public:
    /** 接口 **/
    int videoToImages(const string &logName, const CRM::VideoToImagesReq &req, CRM::VideoToImagesRsp &rsp);

private:
    struct OutPutOptional
    {
        long outputWidth = 0;
        long outputHeight = 0;
    };
    // 保存一帧图像为 PNG 格式
    bool save_frame_as_png(AVFrame* frame, AVCodecContext* png_ctx, int frame_index, const std::string& output_dir);
    // 从输入视频中提取 n 帧图像，保存为 PNG 文件到 output_dir
    int videoToImagesPNG(const std::string& input_file, const std::string& output_dir, int interval_ms, int max_frames = 0, const OutPutOptional *optional = nullptr);
    // 使用 FFmpeg 的 AVIOContext + 自定义内存读回调来模拟文件输入
    // int extract_frames_from_memory(const std::vector<char>& videoData, int interval_ms, int max_frames, std::vector<std::vector<taf::Char>>& outFrames);
    // 抽帧
    int videoToImagesJPG(const std::string& videoPath, const std::string& outputDir, int intervalMs, const OutPutOptional *optional = nullptr);

private:
    // 判断字符串是否以指定后缀结尾
    bool endsWith(const string &str, const string &suffix)
    {
        return str.size() >= suffix.size() &&
            str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
    }
    // 删除目录及其内部文件
    void delete_dir_and_files(const string &dirPath)
    {
        DIR *dir = opendir(dirPath.c_str());
        if (!dir) return;

        struct dirent *entry;
        while ((entry = readdir(dir)) != nullptr)
        {
            if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
                continue;

            string filePath = dirPath + "/" + entry->d_name;
            remove(filePath.c_str()); // 删除文件
        }
        closedir(dir);
        rmdir(dirPath.c_str()); // 删除目录本身
    }
    std::string gen_random(const int len) {
        static const char alphanum[] =
            "0123456789"
            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            "abcdefghijklmnopqrstuvwxyz";
        std::string tmp_s;
        tmp_s.reserve(len);

        for (int i = 0; i < len; ++i) {
            tmp_s += alphanum[rand() % (sizeof(alphanum) - 1)];
        }

        return tmp_s;
    }

};
